package com.securitydome05.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.securitydome05.service.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.context.SecurityContextPersistenceFilter;

import java.util.HashMap;
import java.util.Map;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final MyUserDetailsService myUserDetailsService;

    @Autowired
    public SecurityConfig(MyUserDetailsService myUserDetailsService) {
        this.myUserDetailsService = myUserDetailsService;
    }


    @Bean
    public LoginKaptcahFilter loginKaptcahFilter() throws Exception {
        return new LoginKaptcahFilter(authenticationManager(null));
    }


    @Bean
    public AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
        AuthenticationManagerBuilder builder = http.getSharedObject(AuthenticationManagerBuilder.class);
        builder.userDetailsService(myUserDetailsService);
        return builder.build();
    }



    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf(AbstractHttpConfigurer::disable);              //禁止csrf 跨站请求保护

        http.authorizeHttpRequests(authz -> authz
                        .requestMatchers("/doLogin").permitAll()  // 放行自定义login页面
                        .requestMatchers("/vc.jpg").permitAll()  // 放行自定义login页面
//                        .requestMatchers("/index").permitAll()  // 允许所有用户访问的页面
                        .anyRequest().authenticated()  // 其他所有请求都需要认证
        );

        http.exceptionHandling(exc -> exc
                .authenticationEntryPoint(((request, response, authException) -> {
                    response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
                    response.setStatus(HttpStatus.UNAUTHORIZED.value());
                    response.getWriter().println("认证后才能访问");
                }))
        );

//        http.formLogin(form -> form
//                .loginProcessingUrl("/toLogin")        // 自定义登录处理 URL
//        );

        //开启会话认证
        http.addFilterBefore(new SecurityContextPersistenceFilter(), UsernamePasswordAuthenticationFilter.class);


        http.logout(logout -> logout
                .logoutUrl("/logout")    //自定义注销 URL，logout(默认)
                .logoutSuccessHandler(((request, response, authentication) -> {
                    Map<String, Object> result = new HashMap<>();
                    result.put("msg", "退出成功：" + authentication);
                    result.put("authentication", authentication);
                    response.setStatus(HttpStatus.OK.value());
                    response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
                    String s = new ObjectMapper().writeValueAsString(result);
                    response.getWriter().println(s);

                }))
        );

        http.addFilterAt(loginKaptcahFilter(), UsernamePasswordAuthenticationFilter.class);


        return http.build();
    }

}
